{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CuDNNLSTM\n",
    "98.8% accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "cu_dnnlstm_2 (CuDNNLSTM)     (None, 256)               292864    \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 10)                2570      \n",
      "_________________________________________________________________\n",
      "activation_2 (Activation)    (None, 10)                0         \n",
      "=================================================================\n",
      "Total params: 295,434\n",
      "Trainable params: 295,434\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "Epoch 1/20\n",
      "60000/60000 [==============================] - 5s 80us/step - loss: 0.4171 - acc: 0.8623\n",
      "Epoch 2/20\n",
      "60000/60000 [==============================] - 5s 78us/step - loss: 0.1282 - acc: 0.9605\n",
      "Epoch 3/20\n",
      "60000/60000 [==============================] - 5s 79us/step - loss: 0.0842 - acc: 0.9737\n",
      "Epoch 4/20\n",
      "60000/60000 [==============================] - 5s 85us/step - loss: 0.0636 - acc: 0.9801\n",
      "Epoch 5/20\n",
      "60000/60000 [==============================] - 5s 88us/step - loss: 0.0508 - acc: 0.9846\n",
      "Epoch 6/20\n",
      "60000/60000 [==============================] - 5s 84us/step - loss: 0.0442 - acc: 0.9859\n",
      "Epoch 7/20\n",
      "60000/60000 [==============================] - 5s 87us/step - loss: 0.0364 - acc: 0.9891\n",
      "Epoch 8/20\n",
      "60000/60000 [==============================] - 5s 87us/step - loss: 0.0309 - acc: 0.9902\n",
      "Epoch 9/20\n",
      "60000/60000 [==============================] - 5s 89us/step - loss: 0.0276 - acc: 0.9916\n",
      "Epoch 10/20\n",
      "60000/60000 [==============================] - 5s 87us/step - loss: 0.0261 - acc: 0.9917\n",
      "Epoch 11/20\n",
      "60000/60000 [==============================] - 5s 86us/step - loss: 0.0241 - acc: 0.9928\n",
      "Epoch 12/20\n",
      "60000/60000 [==============================] - 5s 90us/step - loss: 0.0218 - acc: 0.9933\n",
      "Epoch 13/20\n",
      "60000/60000 [==============================] - 5s 92us/step - loss: 0.0183 - acc: 0.9944\n",
      "Epoch 14/20\n",
      "60000/60000 [==============================] - 6s 92us/step - loss: 0.0175 - acc: 0.9942\n",
      "Epoch 15/20\n",
      "60000/60000 [==============================] - 5s 90us/step - loss: 0.0152 - acc: 0.9950\n",
      "Epoch 16/20\n",
      "60000/60000 [==============================] - 5s 89us/step - loss: 0.0145 - acc: 0.9955\n",
      "Epoch 17/20\n",
      "60000/60000 [==============================] - 6s 92us/step - loss: 0.0128 - acc: 0.9962\n",
      "Epoch 18/20\n",
      "60000/60000 [==============================] - 6s 92us/step - loss: 0.0145 - acc: 0.9955\n",
      "Epoch 19/20\n",
      "60000/60000 [==============================] - 5s 92us/step - loss: 0.0103 - acc: 0.9966\n",
      "Epoch 20/20\n",
      "60000/60000 [==============================] - 5s 89us/step - loss: 0.0126 - acc: 0.9962\n",
      "10000/10000 [==============================] - 0s 45us/step\n",
      "\n",
      "Test accuracy: 98.8%\n"
     ]
    }
   ],
   "source": [
    "from __future__ import absolute_import\n",
    "from __future__ import division\n",
    "from __future__ import print_function\n",
    "\n",
    "import numpy as np\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation, CuDNNLSTM\n",
    "from keras.utils import to_categorical, plot_model\n",
    "from keras.datasets import mnist\n",
    "\n",
    "# load mnist dataset\n",
    "(x_train, y_train), (x_test, y_test) = mnist.load_data()\n",
    "\n",
    "# compute the number of labels\n",
    "num_labels = len(np.unique(y_train))\n",
    "\n",
    "# convert to one-hot vector\n",
    "y_train = to_categorical(y_train)\n",
    "y_test = to_categorical(y_test)\n",
    "\n",
    "# resize and normalize\n",
    "image_size = x_train.shape[1]\n",
    "x_train = np.reshape(x_train,[-1, image_size, image_size])\n",
    "x_test = np.reshape(x_test,[-1, image_size, image_size])\n",
    "x_train = x_train.astype('float32') / 255\n",
    "x_test = x_test.astype('float32') / 255\n",
    "\n",
    "# network parameters\n",
    "input_shape = (image_size, image_size)\n",
    "batch_size = 128\n",
    "units = 256\n",
    "dropout = 0.2\n",
    "\n",
    "# model is RNN with 256 units, input is 28-dim vector 28 timesteps\n",
    "model = Sequential()\n",
    "model.add(CuDNNLSTM(units=units,\n",
    "                    input_shape=input_shape))\n",
    "model.add(Dense(num_labels))\n",
    "model.add(Activation('softmax'))\n",
    "model.summary()\n",
    "plot_model(model, to_file='cudnnlstm-mnist.png', show_shapes=True)\n",
    "\n",
    "# loss function for one-hot vector\n",
    "# use of adam optimizer (better than sgd)\n",
    "# accuracy is good metric for classification tasks\n",
    "model.compile(loss='categorical_crossentropy',\n",
    "              optimizer='adam',\n",
    "              metrics=['accuracy'])\n",
    "# train the network\n",
    "model.fit(x_train, y_train, epochs=20, batch_size=batch_size)\n",
    "\n",
    "loss, acc = model.evaluate(x_test, y_test, batch_size=batch_size)\n",
    "print(\"\\nTest accuracy: %.1f%%\" % (100.0 * acc))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
